/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.persistencesubsystem;

import assisisw.smartcal.entitysubsystem.Calendar;
import assisisw.smartcal.entitysubsystem.Event;
import assisisw.smartcal.entitysubsystem.Notification;
import assisisw.smartcal.entitysubsystem.User;
import assisisw.smartcal.utilities.Configuration;
import java.util.List;
import java.util.Objects;
import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;

/**
 *
 * @author Francesco
 */
@Stateless ()
public class PostgreSQLJPAUserDAO implements IUserDAO 
{

    // Static Fields
    
    /***/
    private final static String FIND_ALL_QUERY_STRING = "SELECT u FROM User AS u" ;

    /***/
    private final static String FIND_BY_MAIL_QUERY = "SELECT u FROM User AS u WHERE u.mail = :mail" ;
    
    // Instance Fields
    
    /***/
    private TypedQuery < User > findAllQuery ;
    
    /***/
    private TypedQuery < User > findByNameQuery ;
    
    /***/ 
    @PersistenceContext ( unitName = Configuration.PU_NAME , type = PersistenceContextType.TRANSACTION )
    private EntityManager entityManager ;
    
    // Instance Methods
    
    /***/
    public PostgreSQLJPAUserDAO () {}
    
    /***/
    @PostConstruct
    public void init () 
    {
        findAllQuery = entityManager.createQuery ( FIND_ALL_QUERY_STRING , User.class ) ;        
        //findByNameQuery = entityManager.createQuery ( FIND_BY_MAIL_QUERY , User.class ) ;
    }
    
    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public List < User > findAll () 
    {
        List < User > res ;
        res = findAllQuery.getResultList () ;
        return res ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public User findByMail ( String eMail ) 
    {
        User res ;
        List < User > users ;
        List l ;
        // alternative implementation that causes problems
        //users = findByNameQuery.setParameter ( "mail" , eMail ).getResultList () ;
        //res = ( users != null && users.size()== 1 ) ? users.get ( 0 ) : null ;
        res = entityManager.find(User.class, eMail);
        initializeUser(res);
        return res ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public void insert ( User user ) 
    {
        if ( Objects.nonNull ( user ) )
        {
            entityManager.persist ( user ) ;
            entityManager.flush();
        }
        else
            throw new IllegalArgumentException () ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public void update ( User user ) 
    {
        if ( Objects.nonNull ( user ) )
        {
            entityManager.merge ( user ) ;
            entityManager.flush () ;
        }
        else
            throw new IllegalArgumentException () ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public void remove ( User user ) 
    {
        if ( user != null )
        {
            entityManager.remove ( user ) ;
            entityManager.flush () ;
        }
        else
            throw new IllegalArgumentException () ;
    }

    private static void initializeUser ( User u ) 
    {
        if ( u != null )
        {
            u.getOwnedCalendars ().size () ;
            u.getSharedCalendars().size () ;
            u.getInvitedEvents().size () ;
            u.getNotifications().size () ;
            for ( Calendar c : u.getOwnedCalendars() )
            {
                c.getContainedEvents().size();
                c.getPeopleWhoCanAccess().size(); 
            }
            for ( Calendar c : u.getSharedCalendars () )
            {
                c.getContainedEvents().size();
                c.getPeopleWhoCanAccess().size();
            }
            for ( Event e : u.getInvitedEvents () )
            {
                for ( User u1 : e.getInvitedUsers() ) ;
                e.getNotifications().size();
            }
            for ( Notification n : u.getNotifications() )
                ;
        }
    }
    
}
